package com.handu.luna.core.domain.goods;

import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.*;

import javax.persistence.Entity;
import javax.persistence.Lob;
import javax.persistence.Transient;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.Size;

import com.handu.luna.core.domain.goods.goodsMatch.GoodsMatch;
import com.handu.luna.core.domain.promotion.*;
import com.handu.luna.core.domain.promotion.combo.Combo;
import com.handu.luna.core.domain.user.User;
import com.handu.luna.core.domain.user.UserRank;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaRepository;

import com.handu.luna.core.domain.BasePersistentDomain;
import com.handu.luna.core.domain.Mall;
import com.handu.luna.core.domain.search.SalesPromotionSearch;
import com.handu.luna.core.domain.search.Search4Portal;
import com.handu.luna.core.domain.search.Search4Portal.Direction;
import com.handu.luna.core.domain.search.Search4Portal.SearchOrCategory;
import com.handu.luna.core.domain.searchVo.GoodsSearch;
import com.handu.luna.core.domain.support.GoodsGroupInfo;

@Entity
public class Goods extends BasePersistentDomain<GoodsRepository> {

	
	private long brandId;// 品牌ID
	
	private long categoryId;// 分类ID

	@Size(min = 1, max = 200, message = "商品名称长度不能为空或超过200个字。")
	private String name;// 商品名称

	@Size(min = 0, max = 200, message = "促销标题长度不能为空或超过200个字。")
	private String title;// 促销标题

	@Size(min = 1, max = 10, message = "商品货号长度不能为空或超过10个字。")
	private String goodsSN;// 商品货号

	@Transient
	private Category category;// 商品分类

	@Transient
	private Brand brand;// 商品品牌
	
	@Min(value = 1, message = "本店售价不能低于0")
	private BigDecimal shopPrice;// 本店售价
	
	@Min(value = 1, message = "市场售价不能低于0")
	private BigDecimal marketPrice;// 市场售价
	
	private String goodsPic;// 上传商品图片

	private String thumbGoodsPic;// 上传商品缩略图

	private String longGoodsPic;// 上传长图

	private String goodsVideo;// 商品视频

	@Lob
	private String content;// 详细描述信息

	@Min(value = 0, message = "库存不能小于0")
	private long goodsStore;// 库存

	@Min(value = 0, message = "库存预留量不能小于0")
	private int reservedStore = 0;// 库存预留量


	@Min(value = 0, message = "库存不能小于0")
	private int virtualSales = 0;// 虚拟销售数量
	
	@Min(value = 0, message = "库存不能小于0")
	private int realSales = 0;// 真实销售数量

    @Transient
    private List<SelectRecommend> selectRecommendList;
 
    private String selectRecommends;//加入推荐

	private boolean displayed;// 上下架状态

	private boolean whether;// 能作为普通商品销售

	@Size(min = 0, max = 100, message = "不能超过超过100个字。")
	private String goodsTag;// 商品关键词

	@Size(min = 0, max = 300, message = "不能超过超过300个字。")
	private String shortDescription;// 商品简单描述

	@Min(value = 0, message = "取值范围:0~255,包含0,不包含255。")
	@Max(value = 254, message = "取值范围:0~255,包含0,不包含255。")
	private int goodsManageSort = 100; // 排序

	private String uploadPerson;// 上传人
	
	private Date startDate;//开始时间
	
	private Date endDate;//结束时间	

	private boolean deleted;//是否已删除
	
	private String seokeywords;
	
	private String checkPic;
	
	private int promotion;//是否是促销活动商品
	
	private BigDecimal promotionPrice;//促销价格
	
	private int seckillgroupbuy;//是否是秒杀团购商品
	
	private int seckillgroupbuyNumber;//活动商品数量
	
	private BigDecimal seckillgroupbuyPrice;//活动商品价格
	
	@Transient
	private String mark;
	
    //可使用品牌ID列表
    protected String  attributeIds;
    
    @Transient
    protected List<Long> attributeIdList;
    
    @Transient
    protected List<SKU> SKUList;//SKU
    
    @Transient
    protected List<GoodsAttribute> goodsAttribute;//SKU商品属性
    
    //商品颜色
    protected String  goodsColorIds;
    
    @Transient
    protected List<String> goodsColorIdList;
    
    //商品尺寸
    protected String  goodsSizeIds;
    
    @Transient
    protected List<String> goodsSizeIdList;
    
    @Transient
    private List<String> selelctList;
	
    @Transient
    List<String> goodsColorList;
    
    @Transient
    List<String> goodsSizeList;

    @Transient private CreditGoodsGoods creditGoodsGoods;

    @Transient private CreditPromotionGoods creditPromotionGoods;
    
    @Transient private List<String> picAddresss;

	public List<String> getPicAddresss() {
		return picAddresss;
	}

	public void setPicAddresss(List<String> picAddresss) {
		this.picAddresss = picAddresss;
	}

	public List<String> getGoodsSizeList() {
		return goodsSizeList;
	}

	public void setGoodsSizeList(List<String> goodsSizeList) {
		this.goodsSizeList = goodsSizeList;
	}

	public List<String> getGoodsColorList() {
		return goodsColorList;
	}

	public void setGoodsColorList(List<String> goodsColorList) {
		this.goodsColorList = goodsColorList;
	}

	public List<String> getSelelctList() {
		return selelctList;
	}

	public void setSelelctList(List<String> selelctList) {
		this.selelctList = selelctList;
	}
	
    public String getMark() {
		return mark;
	}

	public void setMark(String mark) {
		this.mark = mark;
	}

	/**
     * 数据库到视图的字段转化
     * 
     */
    public void fromDateBaseToView(Goods goods) {
    	goods.setSelectRecommendList(getSelectRecommendFromString(goods.getSelectRecommends()));
    	goods.setAttributeIdList(getAttributeIdListFromString(goods.getAttributeIds()));
    	goods.setGoodsColorIdList(getGoodsColorIdListFromString(goods.getGoodsColorIds()));
    	goods.setGoodsSizeIdList(getGoodsColorIdListFromString(goods.getGoodsSizeIds()));
    }
    
    /**
     * 视图到数据库的字段转化
     * 
     */
    public void fromViewToDateBase(Goods goods) {
    	goods.setSelectRecommends(getStringFromSelectList(goods.getSelectRecommendList()));
    	goods.setAttributeIds(getStringFromAttributeIdList(goods.getAttributeIdList()));
    	goods.setGoodsColorIds(getStringFromGoodsColorIdList(goods.getGoodsColorIdList()));
    	goods.setGoodsSizeIds(getStringFromGoodsSizeIdList(goods.getGoodsSizeIdList()));
    }
    
    /**
     * 将数据库存储的分类ID字符串序列转换为goodsSizeIdList
     * @param goodsSizeIds
     * @return
     */
    public List<String> getGoodsSizeIdListFromString(String goodsSizeIds) {
        List<String> goodsSizeIdList = new ArrayList<>();
        if(StringUtils.isBlank(goodsSizeIds)) {
            return goodsSizeIdList;
        }
        String[] strArr = goodsSizeIds.split(",");
        for(String str : strArr) {
            try {
            	goodsSizeIdList.add(str);
            } catch (NumberFormatException e) {
                e.printStackTrace();
            }
        }
        return goodsSizeIdList;
    }

    /**
     * 将goodsSizeIdList转换为数据库存储的字符序列，以“，”分隔
     * @param goodsSizeIds
     * @return
     */
    public String getStringFromGoodsSizeIdList(List<String> goodsSizeIdList) {
        if(null == goodsSizeIdList || goodsSizeIdList.size() == 0) {
            return "";
        }

        StringBuilder sb = new StringBuilder();
        for(int i=0; i<goodsSizeIdList.size(); i++) {

            sb.append(goodsSizeIdList.get(i).toString());
            if(i==goodsSizeIdList.size()-1) {
                break;
            }
            sb.append(",");
        }
        return sb.toString();
    }
    
    /**
     * 将数据库存储的分类ID字符串序列转换为goodsColorIdList
     * @param goodsColorIds
     * @return
     */
    public List<String> getGoodsColorIdListFromString(String goodsColorIds) {
        List<String> goodsColorIdList = new ArrayList<>();
        if(StringUtils.isBlank(goodsColorIds)) {
            return goodsColorIdList;
        }
        String[] strArr = goodsColorIds.split(",");
        for(String str : strArr) {
            try {
                goodsColorIdList.add(str);
            } catch (NumberFormatException e) {
                e.printStackTrace();
            }
        }
        return goodsColorIdList;
    }

    /**
     * 将goodsColorIdList转换为数据库存储的字符序列，以“，”分隔
     * @param goodsColorIdList
     * @return
     */
    public String getStringFromGoodsColorIdList(List<String> goodsColorIdList) {
        if(null == goodsColorIdList || goodsColorIdList.size() == 0) {
            return "";
        }

        StringBuilder sb = new StringBuilder();
        for(int i=0; i<goodsColorIdList.size(); i++) {

            sb.append(goodsColorIdList.get(i).toString());
            if(i==goodsColorIdList.size()-1) {
                break;
            }
            sb.append(",");
        }
        return sb.toString();
    }
    
    /**
     * 将数据库存储的品牌ID字符串序列转换为IdList
     * @param brandIds
     * @return
     */
    public List<Long> getAttributeIdListFromString(String attributeIds) {
        List<Long> attributeIdList = new ArrayList<>();
        if(StringUtils.isBlank(attributeIds)) {
            return attributeIdList;
        }
        String[] strArr = attributeIds.split(",");
        for(String str : strArr) {
            try {
                Long attributeId = Long.parseLong(str);
                attributeIdList.add(attributeId);
            } catch (NumberFormatException e) {
                e.printStackTrace();
            }
        }
        return attributeIdList;
    }

    /**
     * 将brangIdList转换为数据库存储的字符序列，以“，”分隔
     * @param brandIdList
     * @return
     */
    public String getStringFromAttributeIdList(List<Long> attributeIdList) {
        if(null == attributeIdList || attributeIdList.size() == 0) {
            return "";
        }

        StringBuilder sb = new StringBuilder();
        for(int i=0; i<attributeIdList.size(); i++) {

            sb.append(attributeIdList.get(i).toString());
            if(i==attributeIdList.size()-1) {
                break;
            }
            sb.append(",");
        }
        return sb.toString();
    }

	
	public enum SelectRecommend {
		BOUTIQUE("精品"), NEW("新品"), HOT("热销");
		public String description;

		SelectRecommend(final String description) {
			this.description = description;
		}
		
        public static SelectRecommend valueOf(int ordinal) {
            if (ordinal < 0 || ordinal >= values().length) {
                throw new IndexOutOfBoundsException("Invalid ordinal");
            }
            return values()[ordinal];
        }
	}

    
    /**
     * 将数据库存储的枚举字符串序列转换为List
     * @param selectRecommends
     * @return
     */
    public List<SelectRecommend> getSelectRecommendFromString(String selectRecommends) {
    	List<SelectRecommend> selectRecommendList = new ArrayList<>();
        if(StringUtils.isBlank(selectRecommends)) {
            return selectRecommendList;
        }
        String[] strArr = selectRecommends.split(",");
        for(String str : strArr) {
            try {
                int selectIndex = Integer.parseInt(str);
                selectRecommendList.add(SelectRecommend.valueOf(selectIndex));
            } catch (NumberFormatException e) {
                e.printStackTrace();
            }
        }
        return selectRecommendList;
    }
    
    
    /**
     * 将useRangeList转换为数据库存储的字符序列，以“，”分隔
     * @param useRangeList
     * @return
     */
    public String getStringFromSelectList(List<SelectRecommend> selectRecommendList) {
        if(null == selectRecommendList || selectRecommendList.size() == 0) {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        for(int i=0; i<selectRecommendList.size(); i++) {

            sb.append(selectRecommendList.get(i).ordinal());
            if(i==selectRecommendList.size()-1) {
                break;
            }
            sb.append(",");
        }
        return sb.toString();
    }

	/**
	 * 初始化信息
	 */
	public void init() {
		brand= context.getBrandRepository().findOne(brandId);
		category = context.getCategoryRepository().findOne(categoryId);
	}
	
	
	
	/**
	 * 查询全部商品
	 * @return
	 */
	public Page<Goods> findAll(Pageable pageable){
		Page<Goods> goodss = context.getGoodsRepository().findAll(pageable);
		for (Goods goods : goodss) {
			goods.init();
		}
		return goodss;
	}
	
	/**
	 * 查询回收站全部商品
	 * @return
	 */
	public Page<Goods> findTrash(Pageable pageable){
		Page<Goods> goodss = context.getGoodsRepository().findTrash(pageable);
		for (Goods goods : goodss) {
			goods.init();
		}
		return goodss;
	}

	public Goods() {
	}

	public Goods(String name, String title, String goodsSN, Category category,
			Brand brand, BigDecimal shopPrice, BigDecimal marketPrice,
			String goodsPic, String thumbGoodsPic, String longGoodsPic,
			String goodsVideo, String content, long goodsStore,
			int reservedStore,int virtualSales,
			List<SelectRecommend> selectRecommendList,String selectRecommends, boolean displayed,
			boolean whether, String goodsTag, String shortDescription,
			int goodsManageSort, String uploadPerson,Date startDate, Date endDate,String seokeywords) {
		super();
		this.name = name;
		this.title = title;
		this.goodsSN = goodsSN;
		this.category = category;
		this.brand = brand;
		this.shopPrice = shopPrice;
		this.marketPrice = marketPrice;
		this.goodsPic = goodsPic;
		this.thumbGoodsPic = thumbGoodsPic;
		this.longGoodsPic = longGoodsPic;
		this.goodsVideo = goodsVideo;
		this.content = content;
		this.goodsStore = goodsStore;
		this.reservedStore = reservedStore;
		this.virtualSales = virtualSales;
		this.selectRecommendList = selectRecommendList;
		this.selectRecommends = selectRecommends;
		this.displayed = displayed;
		this.whether = whether;
		this.goodsTag = goodsTag;
		this.shortDescription = shortDescription;
		this.goodsManageSort = goodsManageSort;
		this.uploadPerson = uploadPerson;
		this.startDate = startDate;
		this.endDate = endDate;
		this.seokeywords = seokeywords;
	}

	public Goods(long brandId,long categoryId,String name, String goodsSN, BigDecimal shopPrice, BigDecimal marketPrice,
			boolean displayed, int goodsManageSort, String uploadPerson,
			long goodsStore) {
		super();
		this.brandId = brandId;
		this.categoryId = categoryId;
		this.name = name;
		this.goodsSN = goodsSN;
		this.shopPrice = shopPrice;
		this.marketPrice = marketPrice;
		this.displayed = displayed;
		this.goodsManageSort = goodsManageSort;
		this.uploadPerson = uploadPerson;
		this.goodsStore = goodsStore;
	}
	
	public Goods(long id,String name,BigDecimal marketPrice,BigDecimal finalPrice,
			int realSales,int virtualSales,Date createdDate,
			String goodsPic, String thumbGoodsPic){
		this.id = id;
		this.name = name;
		this.marketPrice = marketPrice;
		this.showPrice = finalPrice;
		this.realSales = realSales;
		this.virtualSales = virtualSales;
		this.createdDate = createdDate == null ? null:createdDate.toInstant().atZone(ZoneId.of("UTC+08:00"));
		this.goodsPic = goodsPic;
		this.thumbGoodsPic = thumbGoodsPic;
	}

    public CreditPromotionGoods getCreditPromotionGoods() {
        return creditPromotionGoods;
    }

    public void setCreditPromotionGoods(CreditPromotionGoods creditPromotionGoods) {
        this.creditPromotionGoods = creditPromotionGoods;
    }

    public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}
	
	

	public String getGoodsColorIds() {
		return goodsColorIds;
	}

	public void setGoodsColorIds(String goodsColorIds) {
		this.goodsColorIds = goodsColorIds;
	}

	public List<String> getGoodsColorIdList() {
		return goodsColorIdList;
	}

	public void setGoodsColorIdList(List<String> goodsColorIdList) {
		this.goodsColorIdList = goodsColorIdList;
	}

	public String getAttributeIds() {
		return attributeIds;
	}

	public void setAttributeIds(String attributeIds) {
		this.attributeIds = attributeIds;
	}

	public List<Long> getAttributeIdList() {
		return attributeIdList;
	}

	public void setAttributeIdList(List<Long> attributeIdList) {
		this.attributeIdList = attributeIdList;
	}

	public boolean isDeleted() {
		return deleted;
	}

	public void setDeleted(boolean deleted) {
		this.deleted = deleted;
	}

	public int getPromotion() {
		return promotion;
	}

	public void setPromotion(int promotion) {
		this.promotion = promotion;
	}
	
	public BigDecimal getPromotionPrice() {
		return promotionPrice;
	}

	public void setPromotionPrice(BigDecimal promotionPrice) {
		this.promotionPrice = promotionPrice;
	}

	public int getSeckillgroupbuy() {
		return seckillgroupbuy;
	}

	public void setSeckillgroupbuy(int seckillgroupbuy) {
		this.seckillgroupbuy = seckillgroupbuy;
	}

	public int getSeckillgroupbuyNumber() {
		return seckillgroupbuyNumber;
	}

	public void setSeckillgroupbuyNumber(int seckillgroupbuyNumber) {
		this.seckillgroupbuyNumber = seckillgroupbuyNumber;
	}

	public BigDecimal getSeckillgroupbuyPrice() {
		return seckillgroupbuyPrice;
	}

	public void setSeckillgroupbuyPrice(BigDecimal seckillgroupbuyPrice) {
		this.seckillgroupbuyPrice = seckillgroupbuyPrice;
	}

	public String getGoodsSN() {
		return goodsSN;
	}

	public void setGoodsSN(String goodsSN) {
		this.goodsSN = goodsSN;
	}

	public Category getCategory() {
		return category;
	}

	public void setCategory(Category category) {
		this.category = category;
	}

	public Brand getBrand() {
		if (brand == null){
            brand = context.getBrandRepository().findOne(brandId);
        }
        return brand;
	}

	public void setBrand(Brand brand) {
		this.brand = brand;
	}

	public BigDecimal getShopPrice() {
		return shopPrice;
	}

	public void setShopPrice(BigDecimal shopPrice) {
		this.shopPrice = shopPrice;
	}

	public BigDecimal getMarketPrice() {
		return marketPrice;
	}

	public void setMarketPrice(BigDecimal marketPrice) {
		this.marketPrice = marketPrice;
	}

	public String getGoodsPic() {
		return goodsPic;
	}

	public void setGoodsPic(String goodsPic) {
		this.goodsPic = goodsPic;
	}

	public String getThumbGoodsPic() {
		return thumbGoodsPic;
	}

	public void setThumbGoodsPic(String thumbGoodsPic) {
		this.thumbGoodsPic = thumbGoodsPic;
	}

	public String getGoodsVideo() {
		return goodsVideo;
	}

	public void setGoodsVideo(String goodsVideo) {
		this.goodsVideo = goodsVideo;
	}

	public String getContent() {
		return content;
	}

	public void setContent(String content) {
		this.content = content;
	}

	public long getGoodsStore() {
		return goodsStore;
	}

	public void setGoodsStore(long goodsStore) {
		this.goodsStore = goodsStore;
	}

	public int getReservedStore() {
		return reservedStore;
	}

	public void setReservedStore(int reservedStore) {
		this.reservedStore = reservedStore;
	}

	public int getVirtualSales() {
		return virtualSales;
	}

	public void setVirtualSales(int virtualSales) {
		this.virtualSales = virtualSales;
	}

	public List<SelectRecommend> getSelectRecommendList() {
		return selectRecommendList;
	}

	public void setSelectRecommendList(List<SelectRecommend> selectRecommendList) {
		this.selectRecommendList = selectRecommendList;
	}

	public boolean isDisplayed() {
		return displayed;
	}

	public void setDisplayed(boolean displayed) {
		this.displayed = displayed;
	}

	public boolean isWhether() {
		return whether;
	}

	public void setWhether(boolean whether) {
		this.whether = whether;
	}

	public String getGoodsTag() {
		return goodsTag;
	}

	public void setGoodsTag(String goodsTag) {
		this.goodsTag = goodsTag;
	}

	public String getShortDescription() {
		return shortDescription;
	}

	public void setShortDescription(String shortDescription) {
		this.shortDescription = shortDescription;
	}

	public int getGoodsManageSort() {
		return goodsManageSort;
	}

	public void setGoodsManageSort(int goodsManageSort) {
		this.goodsManageSort = goodsManageSort;
	}

	public String getUploadPerson() {
		return uploadPerson;
	}

	public void setUploadPerson(String uploadPerson) {
		this.uploadPerson = uploadPerson;
	}

	public long getBrandId() {
		return brandId;
	}

	public int getRealSales() {
		return realSales;
	}

	public void setRealSales(int realSales) {
		this.realSales = realSales;
	}

	public void setBrandId(long brandId) {
		this.brandId = brandId;
	}

	public long getCategoryId() {
		return categoryId;
	}

	public void setCategoryId(long categoryId) {
		this.categoryId = categoryId;
	}

	public String getLongGoodsPic() {
		return longGoodsPic;
	}

	public void setLongGoodsPic(String longGoodsPic) {
		this.longGoodsPic = longGoodsPic;
	}

	public Date getStartDate() {
		return startDate;
	}

	public void setStartDate(Date startDate) {
		this.startDate = startDate;
	}

	public Date getEndDate() {
		return endDate;
	}

	public void setEndDate(Date endDate) {
		this.endDate = endDate;
	}
	

	public String getSelectRecommends() {
		return selectRecommends;
	}

	public void setSelectRecommends(String selectRecommends) {
		this.selectRecommends = selectRecommends;
	}

	public String getSeokeywords() {
		return seokeywords;
	}

	public void setSeokeywords(String seokeywords) {
		this.seokeywords = seokeywords;
	}

	public void delete() {
		this.setDeleted(true);
		context.getGoodsRepository().save(this);
	}
	
    public String getCheckPic() {
		return checkPic;
	}

	public void setCheckPic(String checkPic) {
		this.checkPic = checkPic;
	}

	public List<SKU> getSKUList() {
		return SKUList;
	}

	public void setSKUList(List<SKU> sKUList) {
		SKUList = sKUList;
	}

	public List<GoodsAttribute> getGoodsAttribute() {
		return goodsAttribute;
	}

	public void setGoodsAttribute(List<GoodsAttribute> goodsAttribute) {
		this.goodsAttribute = goodsAttribute;
	}

	public String getGoodsSizeIds() {
		return goodsSizeIds;
	}

	public void setGoodsSizeIds(String goodsSizeIds) {
		this.goodsSizeIds = goodsSizeIds;
	}

	public List<String> getGoodsSizeIdList() {
		return goodsSizeIdList;
	}

	public void setGoodsSizeIdList(List<String> goodsSizeIdList) {
		this.goodsSizeIdList = goodsSizeIdList;
	}

    public CreditGoodsGoods getCreditGoodsGoods() {
        return creditGoodsGoods;
    }

    public void setCreditGoodsGoods(CreditGoodsGoods creditGoodsGoods) {
        this.creditGoodsGoods = creditGoodsGoods;
    }

    public Goods save(Goods goods) {

        fromViewToDateBase(goods);
        return context.getGoodsRepository().save(goods);

    }

    public Goods findOne(Long id) {

        Goods goods = context.getGoodsRepository().findOne(id);
        fromDateBaseToView(goods);
        return goods;
    }


	public  Specification<Goods> selectCondition(GoodsSearch goodsSearch) {
		return new Specification<Goods>() {
			@Override
			public Predicate toPredicate(Root<Goods> root,
					CriteriaQuery<?> query, CriteriaBuilder builder) {

				Predicate predicate = builder.conjunction();
				List<Expression<Boolean>> expressions = predicate.getExpressions();
				
				expressions.add(builder.equal(root.<Boolean> get("deleted"),false));

				if (NumberUtils.isDigits(goodsSearch.getGoodsId())) {
					expressions.add(builder.equal(root.<Long> get("id"),goodsSearch.getGoodsId())); // 品牌id
				}
				
				if (NumberUtils.isDigits(goodsSearch.getGoodsBrandsId())) {
					expressions.add(builder.equal(root.<Long> get("brandId"),goodsSearch.getGoodsBrandsId())); // 品牌id
				}

				if (NumberUtils.isDigits(goodsSearch.getGoodsCategoryId())) {
					
					List<Long> ids = context.getCategoryRepository().getAllCatIdByParentCollection(goodsSearch.getGoodsCategoryId());
					
					ids.add(Long.parseLong(goodsSearch.getGoodsCategoryId()));
					
					expressions.add(root.<Long> get("categoryId").in(ids)); // 类型id
				}
				if (StringUtils.isNotBlank(goodsSearch.getGoodsDisplayed())) {
					expressions.add(builder.equal(root.<Boolean>get("displayed"), Boolean.valueOf(goodsSearch.getGoodsDisplayed()))); // 商品名字
				}

				if (StringUtils.isNotBlank(goodsSearch.getKeyword())) {
					expressions.add(builder.or( builder.like(root.<String> get("name"), "%"+ goodsSearch.getKeyword() + "%"),builder.like(root.<String> get("goodsSN"),"%" + goodsSearch.getKeyword() + "%"))); // 商品名字

					
				}
				

				if (StringUtils.isNotBlank(goodsSearch.getGoodsUploadPerson())) {
					expressions.add(builder.like(root.<String> get("uploadPerson"), "%"+ goodsSearch.getGoodsUploadPerson() + "%")); // 上传人
				}
				
				SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
				Date date1 = null;
				Date date2 = null;

				if(StringUtils.isNotBlank(goodsSearch.getGoodsStartDate()) && StringUtils.isBlank(goodsSearch.getGoodsEndDate())){
					try {
						date1 = sdf.parse(goodsSearch.getGoodsStartDate());
					} catch (ParseException e) {
						e.printStackTrace();
					}
					ZonedDateTime zoned_start =	date1.toInstant().atZone(ZoneId.of("UTC+08:00"));
					expressions.add(builder.greaterThanOrEqualTo(root.<ZonedDateTime>get("createdDate"), zoned_start)); 
				}
				
				if(StringUtils.isBlank(goodsSearch.getGoodsStartDate())&& StringUtils.isNotBlank(goodsSearch.getGoodsEndDate())){
					try {
						date2 = sdf.parse(goodsSearch.getGoodsEndDate());
					} catch (ParseException e) {
						e.printStackTrace();
					}
					ZonedDateTime zoned_end =	date2.toInstant().atZone(ZoneId.of("UTC+08:00"));
					expressions.add(builder.lessThanOrEqualTo(root.<ZonedDateTime>get("createdDate"), zoned_end)); 
				}

				if(StringUtils.isNotBlank(goodsSearch.getGoodsStartDate()) && StringUtils.isNotBlank(goodsSearch.getGoodsEndDate())){
					
					try {
						date1 = sdf.parse(goodsSearch.getGoodsStartDate());
						date2 = sdf.parse(goodsSearch.getGoodsEndDate());
					} catch (ParseException e) {
						e.printStackTrace();
					}
					ZonedDateTime zoned_start =	date1.toInstant().atZone(ZoneId.of("UTC+08:00"));
					ZonedDateTime zoned_end =	date2.toInstant().atZone(ZoneId.of("UTC+08:00"));
					expressions.add(builder.between(root.<ZonedDateTime>get("createdDate"), zoned_start, zoned_end)); // 创建时间createdTime
				}

				return query.where(predicate).getRestriction();

			}
		};
	}
	
	
	/**
	 * 将controller拼装的domain转化为需要保存到数据库的domain,主要步骤为
	 * 1、在库中查出相同id的domain
	 * 2、遍历allowed filed，将自身允许修改的属性传给库中的domain
	 * 3、将库中的domain属性回传给自身
	 * 
	 * 本方法主要用于防止手动构建form的攻击，并解决createddate等隐藏参数，在页面保存后为空的情况
	 * @param fields controller中定义的allowed filed，使用@InitBinder定义。
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public void merge(String[] fields){
		if(!this.isNew()){
			 
			List<SelectRecommend> list = this.getSelectRecommendList();
			//List<SKU> mergeSKUList = this.getSKUList();
			List<String> mergeGoodsColorIdList = this.getGoodsColorIdList();
			List<String> mergeGoodsSizeIdList = this.getGoodsSizeIdList();
			List<GoodsAttribute> mergeGoodsAttribute =this.getGoodsAttribute();;//SKU商品属性
			List<String> mergeSelelctList =this.getSelelctList();
		    List<String> goodsColorList = this.getGoodsColorList();
		    List<String> goodsSizeList =this.getGoodsSizeList();
			
			Object thisDomainInDB = null;
			try {
                thisDomainInDB = BeanUtils.cloneBean(((JpaRepository) getRepository()).findOne(this.getId()));
			} catch (IllegalAccessException | InstantiationException
					| InvocationTargetException | NoSuchMethodException e1) {
				logger.debug("error in copy merge a domain",e1);
			}			
			for(String field : fields){
				try {
                    String property = BeanUtils.getProperty(this,field);
                    if(field.endsWith("Date")) {
                        Date date = new SimpleDateFormat("EE MMM dd HH:mm:ss 'CST' yyyy", java.util.Locale.US).parse(property);
                        BeanUtils.copyProperty(thisDomainInDB, field, date);
                    }else {
                        BeanUtils.copyProperty(thisDomainInDB, field, property);
                    }
				} catch (IllegalAccessException | InvocationTargetException
						| NoSuchMethodException e) {
					logger.debug("error in copy merge a domain",e);
				} catch (ParseException e) {
                    e.printStackTrace();
                }
            }
			try {
				BeanUtils.copyProperties(this, thisDomainInDB);
				this.setSelectRecommendList(list);
				//this.setSKUList(mergeSKUList);
				this.setGoodsColorIdList(mergeGoodsColorIdList);
				this.setGoodsSizeIdList(mergeGoodsSizeIdList);
				this.setGoodsAttribute(mergeGoodsAttribute);
				this.setSelelctList(mergeSelelctList);
				this.setGoodsSizeList(goodsSizeList);
				this.setGoodsColorList(goodsColorList);
			} catch (IllegalAccessException | InvocationTargetException e) {
				logger.debug("error in copy merge a domain",e);
			}
		}
	}

    public enum SearchType{
        MATCHSEARCH,COMBOSEARCH;
        private SearchType(){}
    }

    /**
     * 搭配管理查询可搭配的商品 ******* 搭配套餐查询
     * 搭配管理  搜索的条件 商品数量<=10 去掉页面上跟该商品搭配的商品(或者数据库中存在primaryGoodsId（商品的id）为该id（该id为商品的id）的记录) 去掉自己 去掉matchGoodsIds（商品id的集合）中包含该商品id的记录
     * 搭配套餐  搜索的条件 去掉页面上已经选择的（或者传过来的为null的话 就使用id（该id为套餐的id）去数据库中查询（若id不为0）） 搜索条件
     * @param searchType  搜索的类型 主要是为了区分是搭配管理搜索还是搭配套餐的搜索
     * @param categoryId 商品分类的id
     * @param brandId 商品品牌的id
     * @param goodsName 商品的名字
     * @param matchedIds 该商品已经搭配的商品ids 若为空则直接根据该商品的id去数据库goodsMatch中查询****页面上已经选择的组成的一个套餐的商品id集合
     * @return
     */
    public Specification<Goods> searchSelectAble(SearchType searchType ,long id,String categoryId,String brandId,String goodsName,String matchedIds){
        return new Specification<Goods>() {
            @Override
            public Predicate toPredicate(Root<Goods> root, CriteriaQuery<?> query, CriteriaBuilder cb) {


                Predicate predicate = cb.conjunction();
                List<Expression<Boolean>> expressions = predicate.getExpressions();

                expressions.add(cb.equal(root.<Boolean> get("deleted"),false));
                expressions.add(cb.equal(root.<Boolean> get("displayed"),true));

                if (StringUtils.isNotBlank(categoryId)){
                    expressions.add(cb.equal(root.<Long>get("categoryId"),Long.parseLong(categoryId)));
                }
                if (StringUtils.isNotBlank(brandId)){
                    expressions.add(cb.equal(root.<Long>get("brandId"),Long.parseLong(brandId)));
                }
                if (StringUtils.isNotBlank(goodsName)){
                    expressions.add(cb.like(root.<String>get("name"),"%"+goodsName+"%"));
                }
                Set<Long> excludGoodsIds = getUnableMatchGoods(searchType,id,matchedIds);
                if (searchType.name().equals("MATCHSEARCH")){//搭配管理需加上限制条件 去掉自己  商品的库存必须小于等于10
                    excludGoodsIds.add(id);
                    expressions.add(cb.le(root.<Long>get("goodsStore"), (long) 10));
                }

                expressions.add(cb.not(root.get("id").in(excludGoodsIds)));



                return query.where(predicate).getRestriction();
            }
        };
    }
    //搭配管理***搭配套餐 使用
    public Set<Long> getUnableMatchGoods(SearchType searchType,long id , String matchedIds){
        Set<Long> excludGoodsIds = new HashSet<Long>();

        //添加数据库中已搭配的商品Id 或者页面上已经选择的（页面上永远是最新的（即使没有保存也应该先从页面上来剔除））
        if(StringUtils.isNotBlank(matchedIds)){
            for(String matchedId:matchedIds.split(",")){
                excludGoodsIds.add(Long.parseLong(matchedId));
            }
        }else{
            if (searchType.name().equals("MATCHSEARCH")){//搭配搜索
                List<GoodsMatch> list1 = context.getGoodsMatchRepository().findByPrimaryGoodsId(id);
                if(list1 != null && list1.size()>0){
                    for(GoodsMatch match:list1){
                        excludGoodsIds.add(match.getCascadGoodsId());
                    }
                }
            }else{//套餐搜索
                Combo combo = context.getComboRepository().findOne(id);
                if (combo!=null){
                    for(String comboGoodsId:combo.getComboGoodsIds().split(",")){
                        if (comboGoodsId.equals("")){
                            break;
                        }
                        excludGoodsIds.add(Long.parseLong(comboGoodsId));
                    }
                }
            }

        }
        return excludGoodsIds;
    }

    /**
     * 搭配套餐使用
     * 根据给定的商品id集合查找商品
     * @param goodsIds 商品id以,分隔
     * @return
     */
    public static Specification<Goods> in(String goodsIds){
        return new Specification<Goods>() {
            @Override
            public Predicate toPredicate(Root<Goods> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                Predicate predicate = cb.conjunction();
                List<Expression<Boolean>> expressions = predicate.getExpressions();

                expressions.add(cb.equal(root.<Boolean> get("deleted"),false));
                List<Long> idList = new LinkedList<Long>();
                for(String id:goodsIds.split(",")){
                    idList.add(Long.parseLong(id));
                }
                expressions.add(root.<Long>get("id").in(idList));
                return query.where(predicate).getRestriction();
            }
        };
    }
    
    /*
     * 优惠活动满购满赠查询商品
     * */
    public Specification<Goods> searchBuygiveGoods(String categoryId,String brandId,String goodsName){
        return new Specification<Goods>() {
            @Override
            public Predicate toPredicate(Root<Goods> root, CriteriaQuery<?> query, CriteriaBuilder cb) {


                Predicate predicate = cb.conjunction();
                List<Expression<Boolean>> expressions = predicate.getExpressions();

                expressions.add(cb.equal(root.<Boolean> get("deleted"),false));
                expressions.add(cb.equal(root.<Boolean> get("displayed"),true));

                if (StringUtils.isNotBlank(categoryId)){
                    expressions.add(cb.equal(root.<Long>get("categoryId"),Long.parseLong(categoryId)));
                }
                if (StringUtils.isNotBlank(brandId)){
                    expressions.add(cb.equal(root.<Long>get("brandId"),Long.parseLong(brandId)));
                }
                if (StringUtils.isNotBlank(goodsName)){
                    expressions.add(cb.like(root.<String>get("name"), "%" + goodsName + "%"));
                }
                return query.where(predicate).getRestriction();
            }
        };
    }
    
/*    
     * 优惠活动查询商品
     * 
    public Specification<Goods> searchActivitiesGoods(long id,String categoryId,String brandId,String goodsName,String matchedIds){
        return new Specification<Goods>() {
            @Override
            public Predicate toPredicate(Root<Goods> root, CriteriaQuery<?> query, CriteriaBuilder cb) {


                Predicate predicate = cb.conjunction();
                List<Expression<Boolean>> expressions = predicate.getExpressions();

                expressions.add(cb.equal(root.<Boolean> get("deleted"),false));
                expressions.add(cb.equal(root.<Boolean> get("displayed"),false));

                if (StringUtils.isNotBlank(categoryId)){
                    expressions.add(cb.equal(root.<Long>get("categoryId"),Long.parseLong(categoryId)));
                }
                if (StringUtils.isNotBlank(brandId)){
                    expressions.add(cb.equal(root.<Long>get("brandId"),Long.parseLong(brandId)));
                }
                if (StringUtils.isNotBlank(goodsName)){
                    expressions.add(cb.like(root.<String>get("name"),"%"+goodsName+"%"));
                }
                Set<Long> excludGoodsIds = getUnableGoods(id,matchedIds);

                expressions.add(cb.not(root.get("id").in(excludGoodsIds)));



                return query.where(predicate).getRestriction();
            }
        };
    }*/
    
  //优惠活动 使用
    public Set<Long> getUnableGoods(long id , String matchedIds){
        Set<Long> excludGoodsIds = new HashSet<Long>();

        //添加数据库中已搭配的商品Id 或者页面上已经选择的（页面上永远是最新的（即使没有保存也应该先从页面上来剔除））
        if(StringUtils.isNotBlank(matchedIds)){
            for(String matchedId:matchedIds.split(",")){
                excludGoodsIds.add(Long.parseLong(matchedId));
            }
        }else{
        	Activities activities = context.getActivitiesRepository().findOne(id);
            if (activities!=null){
                for(String activitiesGoodsId:activities.getActivitiesGoodsids().split(",")){
                    if (activitiesGoodsId.equals("")){
                        break;
                    }
                    excludGoodsIds.add(Long.parseLong(activitiesGoodsId));
                }
            }

        }
        return excludGoodsIds;
    }

    public static Specification<Goods> topicSearchGoods(GoodsSearch goodsSearch) {
		return new Specification<Goods>() {
			@Override
			public Predicate toPredicate(Root<Goods> root,
					CriteriaQuery<?> query, CriteriaBuilder builder) {

				Predicate predicate = builder.conjunction();
				List<Expression<Boolean>> expressions = predicate.getExpressions();

				expressions.add(builder.equal(root.<Boolean> get("deleted"),false));
                expressions.add(builder.equal(root.<Boolean> get("displayed"),true));

				if (NumberUtils.isDigits(goodsSearch.getGoodsBrandsId())) {
					expressions.add(builder.equal(root.<Long> get("brandId"),goodsSearch.getGoodsBrandsId())); // 品牌id
				}

				if (NumberUtils.isDigits(goodsSearch.getGoodsCategoryId())) {
					expressions.add(builder.equal(root.<Long> get("categoryId"), goodsSearch.getGoodsCategoryId())); // 类型id
				}

				if (StringUtils.isNotBlank(goodsSearch.getKeyword())) {
					expressions.add(builder.or( builder.like(root.<String> get("name"), "%"+ goodsSearch.getKeyword() + "%"),builder.like(root.<String> get("goodsSN"),"%" + goodsSearch.getKeyword() + "%"))); // 商品名字
				}

				return query.where(predicate).getRestriction();

			}
		};
	}


	 
    /**
     * 获得商品
     * selectRecommends =BOUTIQUE;精品
	   selectRecommends=NEW;新品
	   selectRecommends=HOT; 热销
     * @param catId  分类Id
     * @param limit  所显示的商品数量
     * @param sort   依据什么来排序 
     * @param orderBy  值为：asc或desc
     * @param other   依据selectRecommends
     * //get_goods(225,5,'sort_order','desc','new')); 
     */
    public List<Goods>  getGoods(long catId,String selectRecommends,String sort,String orderBy,int limit)   //,Pageable pageNum
    {      	
	 	//List<List<Goods>> goodsArr = new ArrayList<>();  Pageable pageable	
  	
	 	List<Goods> goodsArr = new ArrayList<Goods>();		 	
	    List<Long> childrenCatIds = context.getCategoryRepository().getAllCatIdByParentCollection(Long.toString(catId));
	    List<Goods> goodsList = null;
	    int i=0;
	    for (Long categoryId : childrenCatIds) {	    	
	        goodsList = context.getGoodsRepository().findGoodsByCondition(categoryId,selectRecommends,sort,orderBy);
              for(Goods  goods : goodsList){
	    		if(i<limit){
		    	    goodsArr.add(goods); 		    			  
		    	  } 
	    	    i++;
	    	 } 	    			    	     
	    }
	   // List<Goods> goodsArrFinal = handleGoodsPrice(goodsArr);
	    handleGoodsPrice(goodsArr);
	 	return  goodsArr;
	}
    
    
   
	 
	 @SuppressWarnings({ "rawtypes", "unchecked" })
	public List search4Portal(Search4Portal sportal){
		 //初始化商品id容器
		 Set<Long> qualifiedGoodsIds = new HashSet<Long>();
		 
		 //若选择了促销  查找当前正在进行的促销活动中所有的商品，并将商品ID放入 合格容器
		 if(sportal.getIsPromotion()){
			 List<SalesPromotion> salePromotions = context.getSalesPromotionRepository().findAll(SalesPromotion.selectCondition(new SalesPromotionSearch(1)));
			 if(CollectionUtils.isNotEmpty(salePromotions)){
				 List<Long> salePromotionIds = new ArrayList<Long>();
				 for(SalesPromotion sp : salePromotions){
					 salePromotionIds.add(sp.getId());
				 }
				 List<SalesPromotionGoods> salesPromotionGoods = context.getSalesPromotionGoodsRepository().findAll(new SalesPromotionGoods().searchPromotioningGoods(salePromotionIds));
				 if(CollectionUtils.isNotEmpty(salesPromotionGoods)){
					 for(SalesPromotionGoods spg :salesPromotionGoods){
						 qualifiedGoodsIds.add(spg.getGoodsId());
					 }
				 }
			 }
			 if(CollectionUtils.isEmpty(qualifiedGoodsIds)){
				 logger.debug("前台搜索>>>>>>>>>>>>>>>>>>>>>>>>>>>>没有查询到数据!");
				 return null;
			 }
		 }
		 
		 
		 if(sportal.getIsPost4Free()){
			 qualifiedGoodsIds = new PostForFreeActivity().searchPost4Freeing(sportal.getBrand(), qualifiedGoodsIds);
			 
			 if(CollectionUtils.isEmpty(qualifiedGoodsIds)){
				 logger.debug("前台搜索>>>>>>>>>>>>>>>>>>>>>>>>>>>>没有查询到数据!");
				 return null;
			 }
		 }
		 
		 List<Long> excludedAttributeId = new ArrayList<Long>();
		 
		 if(sportal.getGoodAttributes() != null && sportal.getGoodAttributes().length>0){
			 excludedAttributeId = context.getGoodsAttributeRepository().findExcludedAttributeId(sportal.getGoodAttributes());
			 
			 for(String attribute : sportal.getGoodAttributes()){
				 if(CollectionUtils.isNotEmpty(qualifiedGoodsIds)){
					 qualifiedGoodsIds = context.getGoodsAttributeRepository().
							 findGoodsIdByAttributeValuesAndGoodsId(attribute, qualifiedGoodsIds);
				 }else{
					 qualifiedGoodsIds = context.getGoodsAttributeRepository().
							 findGoodsIdByAttributeValues(attribute);
				 }
				 if(CollectionUtils.isEmpty(qualifiedGoodsIds)){
					 logger.debug("前台搜索>>>>>>>>>>>>>>>>>>>>>>>>>>>>没有查询到数据!");
					 return null;
				 }
			 }
		 }
		 
		//处理分类面包屑及左侧分类的展开
		 if(StringUtils.isNotBlank(sportal.getCategory())){
			 Category category = context.getCategoryRepository().findOne(Long.parseLong(sportal.getCategory()));
			 sportal.setCurrentCategory(category);
			 sportal.setParentCategory(category.getParentId()+"");//
			 sportal.setCategoryname(category.getName());
			 //多级 查找出所有的父类   方便面包屑展示
			 if(StringUtils.isNotBlank(category.getParentCollection())){
				 for(String parentId : category.getParentCollection().substring(1).split(",")){
					 if(sportal.getParentcategorys() == null){
						 sportal.setParentcategorys(new ArrayList<Category>());
					 }
					 sportal.getParentcategorys().add(context.getCategoryRepository().findOne(Long.parseLong(parentId)));
				 }
			 }
			 if(!CollectionUtils.isEmpty(context.getCategoryRepository().getAllByCatIdNew(sportal.getCategory()+""))){
				 sportal.setCategorys(context.getCategoryRepository().getAllCatIdByParentCollection(sportal.getCategory()));
				 sportal.getCategorys().add(Long.parseLong(sportal.getCategory()));//父分类下也可以放商品 
			 }
		 }
		 
		 if(StringUtils.isNotBlank(sportal.getBrand())){
			 sportal.setBrandname(context.getBrandRepository().findOne(Long.parseLong(sportal.getBrand())).getName());
		 }
		 
		 //要么查出全部的  要么只查出一部分 不会无结果
		 List<Goods> finalGoodsList = context.getGoodsRepository().findAll(search4PortalAPI(sportal, qualifiedGoodsIds));//至此获得了所有符合条件的商品 接下来需要进行分组以及分页
		 
		 if(CollectionUtils.isEmpty(finalGoodsList)){
			 logger.debug("前台搜索>>>>>>>>>>>>>>>>>>>>>>>>>>>>没有查询到数据!");
			 return null;
		 }
		 
		 List<Long> finalGoodsIdList = new ArrayList<Long>();
		 
		 for(Goods g : finalGoodsList){
			 finalGoodsIdList.add(g.getId());
		 }
		 
		 List finalData = switchHelper(finalGoodsIdList, sportal);
		 if(CollectionUtils.isNotEmpty((Collection) finalData.get(0))){
			 //此处需要转换下 查出来的是Integer或者BigInteger 不是要去的Long
			 List<Long> transform = new LinkedList<Long>();
			 Iterator it = ((Collection)finalData.get(0)).iterator();
			 while(it.hasNext()){
				 transform.add(Long.parseLong(it.next().toString()));
			 }
			 finalData.set(0, transform);
		 }
		 finalData.add(excludedAttributeId);
		 
		 return finalData;
		 //over
		 
	 }
	 @SuppressWarnings({ "unchecked", "rawtypes" })
		public Map<GoodsGroupInfo, List<GoodsGroupInfo>> groupByAttribute(Search4Portal sportal ,List finalData){
		//按属性分组
		 Map<GoodsGroupInfo, List<GoodsGroupInfo>> topSearchGroupByAttribute = new HashMap<GoodsGroupInfo, List<GoodsGroupInfo>>();
		 if(CollectionUtils.isNotEmpty(finalData) && CollectionUtils.isNotEmpty((Collection) finalData.get(0))){
			 List<GoodsGroupInfo> finalGoodsGroupByAttribute;
			 //必须保证每个商品必须设置SKU  如果没有设置则会直接过滤掉
			 if(sportal.getGoodAttributes()!=null && sportal.getGoodAttributes().length>0){
				 finalGoodsGroupByAttribute = context.getGoodsAttributeRepository().
						 goodsAttributeGroup((List<Long>) finalData.get(2), (List<Long>) finalData.get(0));
			 }else{
				 finalGoodsGroupByAttribute = context.getGoodsAttributeRepository().
						 goodsAttributeGroup((List<Long>) finalData.get(0));
			 }
			 
			 if(CollectionUtils.isNotEmpty(finalGoodsGroupByAttribute)){
				 GoodsGroupInfo key;
				 for(GoodsGroupInfo info:finalGoodsGroupByAttribute){
					 key = new GoodsGroupInfo(info.getId(), info.getName());
					 if(topSearchGroupByAttribute.containsKey(key)){
						 topSearchGroupByAttribute.get(key).add(info);
					 }else{
						 List<GoodsGroupInfo> list = new ArrayList<GoodsGroupInfo>();
						 list.add(info);
						 topSearchGroupByAttribute.put(key, list);
					 }
				 }
			 }else{
				 logger.debug("无法再根据属性对商品进行分类");
				 return topSearchGroupByAttribute;
			 }
		 }
			 return topSearchGroupByAttribute;
		 }
		 
		 @SuppressWarnings({ "unchecked", "rawtypes" })
		public Map<Long, GoodsGroupInfo> groupByBrand(Search4Portal sportal ,List finalData){
			//按品牌分组
			 Map<Long,GoodsGroupInfo> topSearchGroupByBrand = new HashMap<Long, GoodsGroupInfo>();
			 if(CollectionUtils.isNotEmpty(finalData) && CollectionUtils.isNotEmpty((Collection) finalData.get(0))){
				 if(StringUtils.isEmpty(sportal.getBrand())){
					 List<GoodsGroupInfo> finalGoodsGroupByBrand = context.getGoodsRepository().
							 groupByBrand4Portal((List<Long>) finalData.get(0));
					 for(GoodsGroupInfo info:finalGoodsGroupByBrand){
						 Brand temp_b = context.getBrandRepository().findOne(info.getId());
						 if(temp_b.isDisplayed()){
							 info.setSubname(context.getBrandRepository().findOne(info.getId()).getName());
							 topSearchGroupByBrand.put(info.getId(), info);
						 }
					 }
				 }
			 }
			 return topSearchGroupByBrand;
		 }
		 
		 /**
		  * 把查出来的商品对其进行按照所属分类分组
		  * 目前只适合两级
		  * 若要修改为任意级
		  * 1 前台样式需要改动 
		  * 2 前台面包屑处需要改动 以及获取面包屑的信息和点击面包屑去掉某个搜索添加后获取面包屑的信息
		  * 3 后台处理
		  *  3.1 若没有选择某个分类  则所搜索界面直接展示顶级分类：查询顶级分类下所有的分类，结合查询出来的符合条件的商品IDS查询出每个顶级分类所包含的商品数 ，发送到前台
		  *  3.2 若选择了某个分类
		  *  	3.2.1  选择的这个分类是叶子，也就是说此分类没有子类，那么前台将不会展示分类的筛选属性（面包屑处会展示所选择的分类）
		  *  	3.2.2 选择的这个分类下面还有分类，那么将只展示该分类下的子分类所包含的商品数（不包含此分类的孙子等分类（若有的话）），此处想当与3.1
		  * @param sportal
		  * @param finalData
		  * @return
		  */
		 @SuppressWarnings({ "rawtypes", "unchecked" })
		public List<GoodsGroupInfo> groupByCategory(Search4Portal sportal,List finalData){
			 List<GoodsGroupInfo> topSearchGroupByCategory = new LinkedList<GoodsGroupInfo>();
			 if(CollectionUtils.isNotEmpty(finalData) && CollectionUtils.isNotEmpty((Collection) finalData.get(0))){
				 //首先获取要搜索框处要展示的分类  然后再将商品划分到这些分类下
				 List<Category> toDisplayedCategory = new ArrayList<Category>(); 
				 if(StringUtils.isNotBlank(sportal.getCategory())){
					 if(CollectionUtils.isNotEmpty(sportal.getCategorys()) && sportal.getCategorys().size()>1){//如果选择了分类 只有不是底层分类的情况下才可以在搜索框展示分类
						 toDisplayedCategory = 
								 context.getCategoryRepository().
								 getSelfCatByParentCollection(
										 sportal.getCurrentCategory().getParentCollection()==null?
										 ","+sportal.getCategory():
											 sportal.getCurrentCategory().getParentCollection()+","+sportal.getCategory());
					 }
				 }else{//展示多顶级分类
					 toDisplayedCategory = context.getCategoryRepository().getTopCategory();
				 }
				 
				 //获取 待展示分类的所有子分类
				 if(CollectionUtils.isNotEmpty(toDisplayedCategory)){
					 for(Category c:toDisplayedCategory){
						 long num = context.getGoodsRepository().
								 findByCategory4Portal(
										 context.getCategoryRepository().getAllDisplayedCatIdByParentCollection(c.getId()+""),
										 (Collection<Long>) finalData.get(0));
						 if(num >0){
							 GoodsGroupInfo ginfo = new GoodsGroupInfo();
							 ginfo.setId(c.getId());
							 ginfo.setSubname(c.getName());
							 ginfo.setNum(num);
							 topSearchGroupByCategory.add(ginfo);
						 }
					 }
				 }
			 }
			 return topSearchGroupByCategory;
		 }
		 
		private void checkPageNumber(List<Long> finalIds,Search4Portal sportal){
			if(CollectionUtils.isNotEmpty(finalIds)){
				if((finalIds.size()/sportal.getPagesize())<sportal.getPage()){
					sportal.setPage(finalIds.size()/sportal.getPagesize());
				}
			}else{
				sportal.setPage(0);
			}
		}
		@SuppressWarnings({ "rawtypes", "unchecked" })
		private List switchHelper(Collection<Long> ids,Search4Portal sportal){
			 List<Long> finalIds;
			 List<Object[]> finalResult;
			 if(StringUtils.isNotBlank(sportal.getMinprice())){
				 if(StringUtils.isNotBlank(sportal.getMaxprice())){
					 finalIds = context.getGoodsRepository().findGoodsIdBetweenPrice4Portal(ids,
							 BigDecimal.valueOf(Double.parseDouble(sportal.getMinprice())),
							 BigDecimal.valueOf(Double.parseDouble(sportal.getMaxprice())));
					 checkPageNumber(finalIds,sportal);
					 if(sportal.getOrder()!=null){
						 switch(sportal.getOrder().name()){
						 case "SALESVOLUME":
							 if(sportal.getDirection()!= null && sportal.getDirection().equals(Direction.DESC)){
								 finalResult = context.getGoodsRepository().
										 findGoodsBetweenPriceOrderBySalesDesc4Portal(ids,
										 BigDecimal.valueOf(Double.parseDouble(sportal.getMinprice())),
										 BigDecimal.valueOf(Double.parseDouble(sportal.getMaxprice())), 
										 sportal.getPage()*sportal.getPagesize(), sportal.getPagesize());
							 }else{
								 finalResult =  context.getGoodsRepository().
										 findGoodsBetweenPriceOrderBySalesAsc4Portal(ids,
												 BigDecimal.valueOf(Double.parseDouble(sportal.getMinprice())),
												 BigDecimal.valueOf(Double.parseDouble(sportal.getMaxprice())), 
												 sportal.getPage()*sportal.getPagesize(), sportal.getPagesize());
							 }
							 break;
						 case "CREATED":
							 if(sportal.getDirection()!= null && sportal.getDirection().equals(Direction.DESC)){
								 finalResult =  context.getGoodsRepository().
										 findGoodsBetweenPriceOrderByCreatedDateDesc4Portal(ids,
												 BigDecimal.valueOf(Double.parseDouble(sportal.getMinprice())),
												 BigDecimal.valueOf(Double.parseDouble(sportal.getMaxprice())), 
												 sportal.getPage()*sportal.getPagesize(), sportal.getPagesize());
							 }else{
								 finalResult =  context.getGoodsRepository().
										 findGoodsBetweenPriceOrderByCreatedDateAsc4Portal(ids,
												 BigDecimal.valueOf(Double.parseDouble(sportal.getMinprice())),
												 BigDecimal.valueOf(Double.parseDouble(sportal.getMaxprice())), 
												 sportal.getPage()*sportal.getPagesize(), sportal.getPagesize());
							 }
							 break;
						 case "PRICE":
							 if(sportal.getDirection()!= null && sportal.getDirection().equals(Direction.DESC)){
								 finalResult =  context.getGoodsRepository().
										 findGoodsBetweenPriceOrderByPriceDesc4Portal(ids,
												 BigDecimal.valueOf(Double.parseDouble(sportal.getMinprice())),
												 BigDecimal.valueOf(Double.parseDouble(sportal.getMaxprice())), 
												 sportal.getPage()*sportal.getPagesize(), sportal.getPagesize());
							 }else{
								 finalResult =  context.getGoodsRepository().
										 findGoodsBetweenPriceOrderByPriceAsc4Portal(ids,
												 BigDecimal.valueOf(Double.parseDouble(sportal.getMinprice())),
												 BigDecimal.valueOf(Double.parseDouble(sportal.getMaxprice())), 
												 sportal.getPage()*sportal.getPagesize(), sportal.getPagesize());
							 }
							 break;
						 default://综合排序
								 finalResult = context.getGoodsRepository().
										 findGoodsBetweenPriceOrderByPriceDesc4Portal(ids,
												 BigDecimal.valueOf(Double.parseDouble(sportal.getMinprice())),
												 BigDecimal.valueOf(Double.parseDouble(sportal.getMaxprice())),
												 sportal.getPage()*sportal.getPagesize(), sportal.getPagesize());
							 break;
						 }
					 }else{//综合排序
							 finalResult = context.getGoodsRepository().
									 findGoodsBetweenPriceOrderByPriceDesc4Portal(ids,
											 BigDecimal.valueOf(Double.parseDouble(sportal.getMinprice())),
											 BigDecimal.valueOf(Double.parseDouble(sportal.getMaxprice())),
											 sportal.getPage()*sportal.getPagesize(), sportal.getPagesize());
					 }
				 }else{
					 finalIds = context.getGoodsRepository().findGoodsIdBetweenPrice4Portal(ids,
							 BigDecimal.valueOf(Double.parseDouble(sportal.getMinprice())),
							 BigDecimal.valueOf(Long.MAX_VALUE));
					 checkPageNumber(finalIds,sportal);
					 if(sportal.getOrder()!=null){
						 switch(sportal.getOrder().name()){
						 case "SALESVOLUME":
							 if(sportal.getDirection()!= null && sportal.getDirection().equals(Direction.DESC)){
								 finalResult = context.getGoodsRepository().
										 findGoodsBetweenPriceOrderBySalesDesc4Portal(ids,
										 BigDecimal.valueOf(Double.parseDouble(sportal.getMinprice())),
										 BigDecimal.valueOf(Long.MAX_VALUE), 
										 sportal.getPage()*sportal.getPagesize(), sportal.getPagesize());
							 }else{
								 finalResult =  context.getGoodsRepository().
										 findGoodsBetweenPriceOrderBySalesAsc4Portal(ids,
												 BigDecimal.valueOf(Double.parseDouble(sportal.getMinprice())),
												 BigDecimal.valueOf(Long.MAX_VALUE), 
												 sportal.getPage()*sportal.getPagesize(), sportal.getPagesize());
							 }
							 break;
						 case "CREATED":
							 if(sportal.getDirection()!= null && sportal.getDirection().equals(Direction.DESC)){
								 finalResult =  context.getGoodsRepository().
										 findGoodsBetweenPriceOrderByCreatedDateDesc4Portal(ids,
												 BigDecimal.valueOf(Double.parseDouble(sportal.getMinprice())),
												 BigDecimal.valueOf(Long.MAX_VALUE), 
												 sportal.getPage()*sportal.getPagesize(), sportal.getPagesize());
							 }else{
								 finalResult =  context.getGoodsRepository().
										 findGoodsBetweenPriceOrderByCreatedDateAsc4Portal(ids,
												 BigDecimal.valueOf(Double.parseDouble(sportal.getMinprice())),
												 BigDecimal.valueOf(Long.MAX_VALUE), 
												 sportal.getPage()*sportal.getPagesize(), sportal.getPagesize());
							 }
							 break;
						 case "PRICE":
							 if(sportal.getDirection()!= null && sportal.getDirection().equals(Direction.DESC)){
								 finalResult =  context.getGoodsRepository().
										 findGoodsBetweenPriceOrderByPriceDesc4Portal(ids,
												 BigDecimal.valueOf(Double.parseDouble(sportal.getMinprice())),
												 BigDecimal.valueOf(Long.MAX_VALUE), 
												 sportal.getPage()*sportal.getPagesize(), sportal.getPagesize());
							 }else{
								 finalResult =  context.getGoodsRepository().
										 findGoodsBetweenPriceOrderByPriceAsc4Portal(ids,
												 BigDecimal.valueOf(Double.parseDouble(sportal.getMinprice())),
												 BigDecimal.valueOf(Long.MAX_VALUE), 
												 sportal.getPage()*sportal.getPagesize(), sportal.getPagesize());
							 }
							 break;
						 default://综合排序
								 finalResult = context.getGoodsRepository().
										 findGoodsBetweenPriceOrderByPriceDesc4Portal(ids,
												 BigDecimal.valueOf(Double.parseDouble(sportal.getMinprice())),
												 BigDecimal.valueOf(Long.MAX_VALUE),
												 sportal.getPage()*sportal.getPagesize(), sportal.getPagesize());
							 break;
						 }
					 }else{//综合排序
							 finalResult = context.getGoodsRepository().
									 findGoodsBetweenPriceOrderByPriceDesc4Portal(ids,
											 BigDecimal.valueOf(Double.parseDouble(sportal.getMinprice())),
											 BigDecimal.valueOf(Long.MAX_VALUE),
											 sportal.getPage()*sportal.getPagesize(), sportal.getPagesize());
					 }
				 }
			 }else{
				if(StringUtils.isNotBlank(sportal.getMaxprice())){
					finalIds = context.getGoodsRepository().findGoodsIdBetweenPrice4Portal(ids,
							 BigDecimal.valueOf(0),
							 BigDecimal.valueOf(Double.parseDouble(sportal.getMaxprice())));
					checkPageNumber(finalIds,sportal);
					 if(sportal.getOrder()!=null){
						 switch(sportal.getOrder().name()){
						 case "SALESVOLUME":
							 if(sportal.getDirection()!= null && sportal.getDirection().equals(Direction.DESC)){
								 finalResult = context.getGoodsRepository().
										 findGoodsBetweenPriceOrderBySalesDesc4Portal(ids,
												 BigDecimal.valueOf(0),
										 BigDecimal.valueOf(Double.parseDouble(sportal.getMaxprice())), 
										 sportal.getPage()*sportal.getPagesize(), sportal.getPagesize());
							 }else{
								 finalResult =  context.getGoodsRepository().
										 findGoodsBetweenPriceOrderBySalesAsc4Portal(ids,
												 BigDecimal.valueOf(0),
												 BigDecimal.valueOf(Double.parseDouble(sportal.getMaxprice())), 
												 sportal.getPage()*sportal.getPagesize(), sportal.getPagesize());
							 }
							 break;
						 case "CREATED":
							 if(sportal.getDirection()!= null && sportal.getDirection().equals(Direction.DESC)){
								 finalResult =  context.getGoodsRepository().
										 findGoodsBetweenPriceOrderByCreatedDateDesc4Portal(ids,
												 BigDecimal.valueOf(0),
												 BigDecimal.valueOf(Double.parseDouble(sportal.getMaxprice())), 
												 sportal.getPage()*sportal.getPagesize(), sportal.getPagesize());
							 }else{
								 finalResult =  context.getGoodsRepository().
										 findGoodsBetweenPriceOrderByCreatedDateAsc4Portal(ids,
												 BigDecimal.valueOf(0),
												 BigDecimal.valueOf(Double.parseDouble(sportal.getMaxprice())), 
												 sportal.getPage()*sportal.getPagesize(), sportal.getPagesize());
							 }
							 break;
						 case "PRICE":
							 if(sportal.getDirection()!= null && sportal.getDirection().equals(Direction.DESC)){
								 finalResult =  context.getGoodsRepository().
										 findGoodsBetweenPriceOrderByPriceDesc4Portal(ids,
												 BigDecimal.valueOf(0),
												 BigDecimal.valueOf(Double.parseDouble(sportal.getMaxprice())), 
												 sportal.getPage()*sportal.getPagesize(), sportal.getPagesize());
							 }else{
								 finalResult =  context.getGoodsRepository().
										 findGoodsBetweenPriceOrderByPriceAsc4Portal(ids,
												 BigDecimal.valueOf(0),
												 BigDecimal.valueOf(Double.parseDouble(sportal.getMaxprice())), 
												 sportal.getPage()*sportal.getPagesize(), sportal.getPagesize());
							 }
							 break;
						 default://综合排序
								 finalResult = context.getGoodsRepository().
										 findGoodsBetweenPriceOrderByPriceDesc4Portal(ids,
												 BigDecimal.valueOf(0),
												 BigDecimal.valueOf(Double.parseDouble(sportal.getMaxprice())),
												 sportal.getPage()*sportal.getPagesize(), sportal.getPagesize());
					 }
					}else{//综合排序
							 finalResult = context.getGoodsRepository().
									 findGoodsBetweenPriceOrderByPriceDesc4Portal(ids,
											 BigDecimal.valueOf(0),
											 BigDecimal.valueOf(Double.parseDouble(sportal.getMaxprice())),
											 sportal.getPage()*sportal.getPagesize(), sportal.getPagesize());
					}
				}else{
					finalIds = (List<Long>) ids;
					checkPageNumber(finalIds,sportal);
					if(sportal.getOrder()!=null){
						 switch(sportal.getOrder().name()){
						 case "SALESVOLUME":
							 if(sportal.getDirection()!= null && sportal.getDirection().equals(Direction.DESC)){
								 finalResult = context.getGoodsRepository().
										 findGoodsBetweenPriceOrderBySalesDesc4Portal(ids,
												 BigDecimal.valueOf(0),
										 BigDecimal.valueOf(Long.MAX_VALUE), 
										 sportal.getPage()*sportal.getPagesize(), sportal.getPagesize());
							 }else{
								 finalResult =  context.getGoodsRepository().
										 findGoodsBetweenPriceOrderBySalesAsc4Portal(ids,
												 BigDecimal.valueOf(0),
												 BigDecimal.valueOf(Long.MAX_VALUE), 
												 sportal.getPage()*sportal.getPagesize(), sportal.getPagesize());
							 }
							 break;
						 case "CREATED":
							 if(sportal.getDirection()!= null && sportal.getDirection().equals(Direction.DESC)){
								 finalResult =  context.getGoodsRepository().
										 findGoodsBetweenPriceOrderByCreatedDateDesc4Portal(ids,
												 BigDecimal.valueOf(0),
												 BigDecimal.valueOf(Long.MAX_VALUE), 
												 sportal.getPage()*sportal.getPagesize(), sportal.getPagesize());
							 }else{
								 finalResult =  context.getGoodsRepository().
										 findGoodsBetweenPriceOrderByCreatedDateAsc4Portal(ids,
												 BigDecimal.valueOf(0),
												 BigDecimal.valueOf(Long.MAX_VALUE), 
												 sportal.getPage()*sportal.getPagesize(), sportal.getPagesize());
							 }
							 break;
						 case "PRICE":
							 if(sportal.getDirection()!= null && sportal.getDirection().equals(Direction.DESC)){
								 finalResult =  context.getGoodsRepository().
										 findGoodsBetweenPriceOrderByPriceDesc4Portal(ids,
												 BigDecimal.valueOf(0),
												 BigDecimal.valueOf(Long.MAX_VALUE), 
												 sportal.getPage()*sportal.getPagesize(), sportal.getPagesize());
							 }else{
								 finalResult =  context.getGoodsRepository().
										 findGoodsBetweenPriceOrderByPriceAsc4Portal(ids,
												 BigDecimal.valueOf(0),
												 BigDecimal.valueOf(Long.MAX_VALUE), 
												 sportal.getPage()*sportal.getPagesize(), sportal.getPagesize());
							 }
							 break;
						 default://综合排序
								 finalResult = context.getGoodsRepository().
										 findGoodsBetweenPriceOrderByPriceDesc4Portal(ids,
												 BigDecimal.valueOf(0),
												 BigDecimal.valueOf(Long.MAX_VALUE),
												 sportal.getPage()*sportal.getPagesize(), sportal.getPagesize());
							 break;
						 }
					 }else{//综合排序
							 finalResult = context.getGoodsRepository().
									 findGoodsBetweenPriceOrderByPriceDesc4Portal(ids,
											 BigDecimal.valueOf(0),
											 BigDecimal.valueOf(Long.MAX_VALUE),
											 sportal.getPage()*sportal.getPagesize(), sportal.getPagesize());
					 }			 
				}
			 }
			 
			 //添加商品相册图片
			 List<Goods> finalGoods = new LinkedList<Goods>();
			 if(CollectionUtils.isNotEmpty(finalResult)){
				 Goods g;
				 DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
				 PageRequest pageable = new PageRequest(0, 5);
				 for(Object[] obj : finalResult){
					 try {
						g = new Goods(
								 Long.parseLong(obj[0].toString()), obj[1].toString(),
								 obj[2]==null?BigDecimal.ZERO:BigDecimal.valueOf(Double.parseDouble(obj[2].toString())),
								 obj[3]==null?BigDecimal.ZERO:BigDecimal.valueOf(Double.parseDouble(obj[3].toString())),
								 obj[4]==null?0:Integer.parseInt(obj[4].toString()), 
								 obj[5]==null?0:Integer.parseInt(obj[5].toString()), 
								 obj[6]==null?null:df.parse(obj[6].toString()), 
								 obj[7]==null?null:obj[7].toString(), 
								 obj[8]==null?null:obj[8].toString());
						if(sportal.getSc().equals(SearchOrCategory.CATEGORY)){
							g.setPicAddresss(context.getGoodsAttributeRepository().findGoodsAttributePic(g.getId(), pageable).getContent());
						}
						finalGoods.add(g);
					} catch (NumberFormatException e) {
						logger.error("封装商品转换数字失败");
					} catch (ParseException e) {
						logger.error("封装商品转换日期失败");
					}
					 
				 }
			 }
			 
			 List list = new ArrayList();
			 list.add(finalIds);
			 list.add(finalGoods);
			 return list;
		 }
	 
	 public static Specification<Goods> search4PortalAPI(Search4Portal sportal,Set<Long> qualifiedGoodsIds){
		 return new Specification<Goods>() {

			@Override
			public Predicate toPredicate(Root<Goods> root,
					CriteriaQuery<?> query, CriteriaBuilder cb) {
				Predicate predicate = cb.conjunction();
				List<Expression<Boolean>> expressions = predicate.getExpressions();
				expressions.add(cb.equal(root.<Boolean> get("deleted"),false));
                expressions.add(cb.equal(root.<Boolean> get("displayed"),true));
				if(StringUtils.isNotBlank(sportal.getBrand())){
					expressions.add(cb.equal(root.get("brandId"), Long.parseLong(sportal.getBrand())));
				}
				if(StringUtils.isNotBlank(sportal.getCategory())){
					if(CollectionUtils.isNotEmpty(sportal.getCategorys())){
						expressions.add(root.get("categoryId").in(sportal.getCategorys()));
					}else{
						expressions.add(cb.equal(root.get("categoryId"), Long.parseLong(sportal.getCategory())));
					}
				}
				
				if(StringUtils.isNotBlank(sportal.getName())){
					expressions.add(cb.like(root.get("name"),"%"+sportal.getName()+"%"));
				}
				if(CollectionUtils.isNotEmpty(qualifiedGoodsIds)){
					expressions.add(root.get("id").in(qualifiedGoodsIds));
				}
				
				return query.where(predicate).getRestriction();
			}
		};
	 }
	 
	 
	 public List<Category> groupGoodsByCategory(){
		 Mall mall=new Mall();	
		 mall.init();
		 List<Category> list = mall.getAllCategories();//所有分类
		 for (Category category : list) {
			 if(StringUtils.isNotBlank(category.getParentCollection())){
				 category.init(category.getId(),true);
			 }
		 }
		 List<Category> parentCategory = mall.getCategories();//父类
		 
		 sortCollection(parentCategory);
		 return parentCategory;
	 }
	 
	 private void sortCollection(List<Category> categorys){
		 Iterator<Category> it = categorys.iterator();
		 while(it.hasNext()){
			 Category c = it.next();
			 if(!c.isDisplayed()){
				 it.remove();
			 }
		 }
		 Collections.sort(categorys, new Comparator<Category>() {
			 @Override
			 public int compare(Category o1, Category o2) {
				 return (int) (o1.getDisplayOrder()-o2.getDisplayOrder());
			 }
		 });
		 for(Category c : categorys){
			 if(CollectionUtils.isNotEmpty(c.getSubCategories())){
				 sortCollection(c.getSubCategories());
			 }
		 }
	 }
	 
	 private enum OrderBy{
		 SALES,CREATEDDATE;
	 }
	 
	 private static Specification<Goods> findTopTen(Search4Portal sportal,OrderBy order){
		 return new Specification<Goods>() {
			
			@Override
			public Predicate toPredicate(Root<Goods> root, CriteriaQuery<?> query,
					CriteriaBuilder cb) {
				Predicate predicate = cb.conjunction();
                List<Expression<Boolean>> expressions = predicate.getExpressions();

                expressions.add(cb.equal(root.<Boolean> get("deleted"),false));
                expressions.add(cb.equal(root.<Boolean> get("displayed"),true));
                
                if(StringUtils.isNotBlank(sportal.getCategory())){
	       			if(!CollectionUtils.isNotEmpty(sportal.getCategorys())){//子类
	       				 expressions.add(cb.equal(root.get("categoryId"), Long.parseLong(sportal.getCategory())));
	       			}else{//父类
	       				 expressions.add(root.get("categoryId").in(sportal.getCategorys()));
	       			}
       		 	}
                
                if(order.name().equals("SALES")){
                	query.orderBy(cb.desc(root.get("virtualSales")));
                }else if(order.name().equals("CREATEDDATE")){
                	query.orderBy(cb.desc(root.get("createdDate")));
                }
				return query.where(predicate).getRestriction();
			}
		};
	 }
	 
	 public List<Goods> findTopSalesGoods(Search4Portal sportal){
		 
		 Page<Goods> topSales  = context.getGoodsRepository().findAll(findTopTen(sportal, OrderBy.SALES),new PageRequest(0, 10));
		 //处理价格
		 handleGoodsPrice(topSales.getContent());
		 
		 return CollectionUtils.isNotEmpty(topSales.getContent())?topSales.getContent():new ArrayList<Goods>();
	 }
	 
	 public List<Goods> findNewGoods(Search4Portal sportal){
		 
		 Page<Goods> topSales  = context.getGoodsRepository().findAll(findTopTen(sportal, OrderBy.CREATEDDATE),new PageRequest(0, 10));
		 
		 //处理价格
		 handleGoodsPrice(topSales.getContent());
		 
		 return CollectionUtils.isNotEmpty(topSales.getContent())?topSales.getContent():new ArrayList<Goods>();
	 }
	 //处理最后要展示的商品的价格  这里只考虑促销价格 不考虑团购秒杀价格
	 public void handleGoodsPrice(Collection<Goods> goods){
		 if(CollectionUtils.isNotEmpty(goods)){
			 for(Goods g : goods){
				 Page<SalesPromotion> uniqueSalesPromotion = context.getSalesPromotionGoodsRepository().
						 findUniqueSalesPromotionByGoodsId(g.getId(), new Date(), new PageRequest(0, 1));
				 if(uniqueSalesPromotion.hasContent()){
					 g.setShowPrice(context.getSalesPromotionGoodsRepository().findBySalesPromotionIdAndGoodsId(
							 uniqueSalesPromotion.getContent().get(0).getId(), g.getId()).getGoodsPrice());
				 }else{
					 g.setShowPrice(g.getShopPrice());
				 }
			 }
		 }
	 }



    /********************************************************************************************************************************************
    *                                                               商品详情页
    *                                                                 开始
    *
    *
    *********************************************************************************************************************************************/
    //最终价格类型列表
    public enum UltimatePriceType {
        SECKILL("秒杀价"),GROUPBUY("团购价"),SALESPROMOTION("促销价"),USERRANK("用户级别"),SHOP("本店价格");

        public String description;
        UltimatePriceType(String description) {
            this.description = description;
        }
    }

    public enum SecKillGroupBuyZone {
        UNACTIVATED("即将开始"),ACTIVATING("正在进行"),SOLDOUT("已卖光");

        public String description;
        SecKillGroupBuyZone(String description) {
            this.description = description;
        }
    }

    //最终价格类型
    @Transient private UltimatePriceType ultimatePriceType;
    //如果是促销活动 需要显示促销活动名称
    @Transient private String salesPromotionName;
    //最终价格
    @Transient private BigDecimal ultimatePrice;
    //最终折扣
    @Transient private BigDecimal ultimateDiscount;
    //所有活动
    @Transient private Map<String,Promotion> promotionMap;
    //优惠活动
    @Transient private List<Activities> activitiesList;
    //会员等级价格列表
    @Transient private Map<String,BigDecimal> userRankPriceMap;
    //颜色图片列表
    @Transient private List<String> colorPicList;
    //显示价格
    @Transient private BigDecimal showPrice;
    //倒计时
    @Transient private long countDown;
    //团购秒杀的时间段(未开始,正在进行,已卖光)
    @Transient private SecKillGroupBuyZone secKillGroupBuyZone;



    public Goods initGoodsInfo(User user) {

        //1初始化最终售价（秒杀，团购，会员等级价格，促销活动价格）
        initUltimate(user);
        //2初始化所有会员等级价格
        initUserRankPriceMap();
        //3初始化SKU属性（剔除库存量为0的属性）
        initAttribute();
        //4初始化优惠活动
        initActivitiesList(user);

        return this;
    }

    public Page<Goods> initShowPrice(Page<Goods> goodsPage,User user) {
        List<Goods> goodsList = goodsPage.getContent();
        for(Goods goods : goodsList) {
            initShowPrice(goods,user);
        }
        return goodsPage;
    }

    public Goods initShowPrice(Goods goods,User user) {
        goods.setShowPrice(goods.getShopPrice());
        if(user == null) {
            return goods;
        }

        //查看当前用户 是否有 促销活动
        //①查找此商品当前正在进行的促销活动列表
        List<SalesPromotion> salesPromotionList = context.getSalesPromotionGoodsRepository().findCurrentSalesPromotionByGoodsId(goods.getId(),new Date());
        if(CollectionUtils.isNotEmpty(salesPromotionList)) {
            //②如果存在,取得创建时间最晚的促销活动
            SalesPromotion salesPromotion = salesPromotionList.get(0);
            //③判断当前用户的用户级别 是否享有此促销活动
            if(salesPromotion.getUserRankIdList().contains(user.getUserRankId())) {
                //④如果享有此促销活动 查询此促销活动商品的详细信息
                SalesPromotionGoods salesPromotionGoods = context.getSalesPromotionGoodsRepository().findBySalesPromotionIdAndGoodsId(Long.valueOf(salesPromotion.getId()),goods.getId());
                goods.setShowPrice(salesPromotionGoods.getGoodsPrice());
            }
        }
        return goods;
    }

    //4初始化优惠活动
    public void initActivitiesList(User user) {
        // 先判断用户等级
        activitiesList = new ArrayList<>();
        List<Activities> currentActiviesList = context.getActivitiesRepository().findCurrent(new Date());
        for(Activities activities : currentActiviesList) {
            if(activities.getActivitiesRange() == Activities.ActivitiesRange.ALL) {
                activitiesList.add(activities);
            }else if(activities.getActivitiesRange() == Activities.ActivitiesRange.CATBRAND) {
                // wangzailiang 按多品牌??????
                if(this.brandId == activities.getBrands()) {
                    if(activities.getCategorysIdList().contains(this.categoryId)) {
                        activitiesList.add(activities);
                    }
                }
            }else if(activities.getActivitiesRange() == Activities.ActivitiesRange.GOODS) {
                for(Goods goods : activities.getActivitiesGoods()) {
                    if(goods.id == this.id) {
                        activitiesList.add(activities);
                    }
                }
            }
        }
    }

    //3初始化SKU属性（剔除库存量为0的属性）
    // 剔除库存量为0的属性
    public void initAttribute() {

        goodsSizeIdList = this.getGoodsSizeIdListFromString(goodsSizeIds);
        goodsColorIdList = this.getGoodsColorIdListFromString(goodsColorIds);
        colorPicList = new ArrayList<>();
        for(String color : goodsColorIdList) {
            GoodsAttribute temp = context.getGoodsAttributeRepository().findGoodsAttributeByGoodsIdAndName(this.id,color);
            if(temp != null) {
                colorPicList.add(temp.getAttributePic());
            }else {
                colorPicList.add("DEFAULT");
            }

        }

    }

    //2初始化所有会员等级价格
    public void initUserRankPriceMap() {
        userRankPriceMap = new LinkedHashMap<String,BigDecimal>();
        List<UserRank> userRankList = context.getUserRankRepository().findAllNotSpecial();
        for(UserRank userRank : userRankList) {
            userRankPriceMap.put(userRank.getRankName(),BigDecimal.valueOf(userRank.getGoodsSale()).multiply(this.shopPrice).divide(new BigDecimal(100)));
        }
    }

    //1初始化最终售价（秒杀，团购，会员等级价格，促销活动价格）
    public void initUltimate(User user) {

        if(null == user) {
            ultimatePrice = this.getShopPrice();
            ultimatePriceType = UltimatePriceType.SHOP;
            ultimateDiscount = ultimatePrice.multiply(BigDecimal.valueOf(10.0)).divide(shopPrice, 10, BigDecimal.ROUND_HALF_UP);
            return;
        }
        /**
         * 查看当前用户 是否有当前正在进行的秒杀团购
         */
        //①查询当前正在进行的秒杀团购
        SecKillGroupBuy currentSecKillGroupBuy = context.getSecKillGroupBuyGoodsRepository().findCurrentSecKillGroupBuyByGoodsId(this.id,new Date());
        if(currentSecKillGroupBuy != null) {
            //②判断当前用户是否能享有此秒杀团购
           // if(currentSecKillGroupBuy.getUserRankIdList().contains(userRankId)) {
                //③如果享有此秒杀团购 查询当前进行的秒杀团购商品的详情
                SecKillGroupBuyGoods secKillGroupBuyGoods = context.getSecKillGroupBuyGoodsRepository().findCurrentSecKillGroupBuyGoodsIdAndGoodsId(Integer.parseInt(currentSecKillGroupBuy.getId().toString()), this.id);
                // 需要考虑秒杀 或者 团购 商品重复的问题 (初步定后台控制 还没实现)
                //④初始化最终价格和最终价格类型
                ultimatePrice = secKillGroupBuyGoods.getGoodsPrice();
                secKillGroupBuyZone = SecKillGroupBuyZone.ACTIVATING;
                if(currentSecKillGroupBuy.getSecKillGroupBuyStatus() == SecKillGroupBuy.SecKillGroupBuyStatus.GROUPBUY) {
                    ultimatePriceType = UltimatePriceType.GROUPBUY;
                }else {
                    ultimatePriceType = UltimatePriceType.SECKILL;
                }
                //⑤如果是团购商品直接返回
            ultimateDiscount = ultimatePrice.multiply(BigDecimal.valueOf(10.0)).divide(shopPrice, 10, BigDecimal.ROUND_HALF_UP);
                return;
            //}
        }

        /**
         * 查看当前用户 是否有即将开始的秒杀团购(24小时内)
         */
        //①查询当前即将开始的秒杀团购
        SecKillGroupBuy secKillGroupBuy = context.getSecKillGroupBuyGoodsRepository().findUnActivatedSecKillGroupBuyByGoodsId(this.id,new Date());
        SecKillGroupBuy unActivitedSecKillGroupBuy = null;
        if( secKillGroupBuy != null) {
        	
        	long millsCha = secKillGroupBuy.getBeginTime().getTime() - System.currentTimeMillis();
        	 if(millsCha/1000/60/60 < 24) {
                 unActivitedSecKillGroupBuy = secKillGroupBuy;
             }
        }
       

        if(unActivitedSecKillGroupBuy != null) {
            //②判断当前用户是否能享有此秒杀团购
            //if(unActivitedSecKillGroupBuy.getUserRankIdList().contains(userRankId)) {
                //③如果享有此秒杀团购 查询当前进行的秒杀团购商品的详情
                SecKillGroupBuyGoods secKillGroupBuyGoods = context.getSecKillGroupBuyGoodsRepository().findCurrentSecKillGroupBuyGoodsIdAndGoodsId(Integer.parseInt(unActivitedSecKillGroupBuy.getId().toString()), this.id);
                // 需要考虑秒杀 或者 团购 商品重复的问题 (初步定后台控制 还没实现)
                //④初始化最终价格和最终价格类型
                ultimatePrice = secKillGroupBuyGoods.getGoodsPrice();
                secKillGroupBuyZone = SecKillGroupBuyZone.UNACTIVATED;
                if(unActivitedSecKillGroupBuy.getSecKillGroupBuyStatus() == SecKillGroupBuy.SecKillGroupBuyStatus.GROUPBUY) {
                    ultimatePriceType = UltimatePriceType.GROUPBUY;
                }else {
                    ultimatePriceType = UltimatePriceType.SECKILL;
                }
                //⑤如果是团购商品直接返回
                ultimateDiscount = ultimatePrice.multiply(BigDecimal.valueOf(10.0)).divide(shopPrice, 10, BigDecimal.ROUND_HALF_UP);
                return;
            //}
        }

        brand = context.getBrandRepository().findOne(brandId);
        //取得当前用户的折扣和会员等级ID
        UserRank userRank = context.getUserRankRepository().findOne(user.getUserRankId());

        //按用户等级来折扣
        ultimatePrice = this.getShopPrice().multiply(BigDecimal.valueOf(userRank.getGoodsSale()).divide(BigDecimal.valueOf(100)));
        ultimatePriceType = UltimatePriceType.USERRANK;

        //查看当前用户 是否有 促销活动
        //①查找此商品当前正在进行的促销活动列表
        List<SalesPromotion> salesPromotionList = context.getSalesPromotionGoodsRepository().findCurrentSalesPromotionByGoodsId(this.id,new Date());
        if(CollectionUtils.isNotEmpty(salesPromotionList)) {
            //②如果存在,取得创建时间最晚的促销活动
            SalesPromotion salesPromotion = salesPromotionList.get(0);
            //③判断当前用户的用户级别 是否享有此促销活动
            if(salesPromotion.getUserRankIdList().contains(user.getUserRankId())) {
                //④如果享有此促销活动 查询此促销活动商品的详细信息
                SalesPromotionGoods salesPromotionGoods = context.getSalesPromotionGoodsRepository().findBySalesPromotionIdAndGoodsId(Long.valueOf(salesPromotion.getId()),this.id);
                //⑤促销价格与用户等级折扣后的价格比较 哪个价格低显示哪一个 如果两个价格相等 显示促销价格
                if(salesPromotionGoods.getGoodsPrice().compareTo(ultimatePrice) != 1) {
                    ultimatePrice = salesPromotionGoods.getGoodsPrice();
                    ultimatePriceType = UltimatePriceType.SALESPROMOTION;
                }
            }
        }

        if(ultimatePriceType == UltimatePriceType.SALESPROMOTION) {
            salesPromotionName = salesPromotionList.get(0).getSalesPromotionName();
        }

        ultimateDiscount = ultimatePrice.multiply(BigDecimal.valueOf(10.0)).divide(shopPrice, 10, BigDecimal.ROUND_HALF_UP);
    }

    public Map<String, BigDecimal> getUserRankPriceMap() {
        return userRankPriceMap;
    }

    public void setUserRankPriceMap(Map<String, BigDecimal> userRankPriceMap) {
        this.userRankPriceMap = userRankPriceMap;
    }

    public List<Activities> getActivitiesList() {
        return activitiesList;
    }

    public void setActivitiesList(List<Activities> activitiesList) {
        this.activitiesList = activitiesList;
    }

    public String getSalesPromotionName() {
        return salesPromotionName;
    }

    public void setSalesPromotionName(String salesPromotionName) {
        this.salesPromotionName = salesPromotionName;
    }

    public UltimatePriceType getUltimatePriceType() {
        return ultimatePriceType;
    }

    public void setUltimatePriceType(UltimatePriceType ultimatePriceType) {
        this.ultimatePriceType = ultimatePriceType;
    }

    public BigDecimal getUltimatePrice() {
        return ultimatePrice;
    }

    public void setUltimatePrice(BigDecimal ultimatePrice) {
        this.ultimatePrice = ultimatePrice;
    }

    public BigDecimal getUltimateDiscount() {
        return ultimateDiscount;
    }

    public void setUltimateDiscount(BigDecimal ultimateDiscount) {
        this.ultimateDiscount = ultimateDiscount;
    }

    public Map<String, Promotion> getPromotionMap() {
        return promotionMap;
    }

    public void setPromotionMap(Map<String, Promotion> promotionMap) {
        this.promotionMap = promotionMap;
    }

    public List<String> getColorPicList() {
        return colorPicList;
    }

    public void setColorPicList(List<String> colorPicList) {
        this.colorPicList = colorPicList;
    }

    public BigDecimal getShowPrice() {
        return showPrice;
    }

    public void setShowPrice(BigDecimal showPrice) {
        this.showPrice = showPrice;
    }

    public long getCountDown() {
        return countDown;
    }

    public void setCountDown(long countDown) {
        this.countDown = countDown;
    }

    public SecKillGroupBuyZone getSecKillGroupBuyZone() {
        return secKillGroupBuyZone;
    }

    public void setSecKillGroupBuyZone(SecKillGroupBuyZone secKillGroupBuyZone) {
        this.secKillGroupBuyZone = secKillGroupBuyZone;
    }

    /********************************************************************************************************************************************
    *                                                              商品详情页
    *                                                                 结束
    *
    *
    *********************************************************************************************************************************************/

}
